source('../settings/settings.R')
source('commonFunctions.R')
drive1 <- read.csv('../data/processed/analysis/TT1_Drive_1_PP.csv')
drive2 <- read.csv('../data/processed/Analysis/TT1_Drive_2_PP.csv')
drive3 <- read.csv('../data/processed/Analysis/TT1_Drive_3_PP.csv')
drive4 <- read.csv('../data/processed/Analysis/TT1_Drive_4_PP.csv', stringsAsFactors = T)
set.seed(43)
combinedDf <- cbind(drive4, 
                    drive1$MeanPP_Seg0, 
                    drive2$MeanPP, drive3$MeanPP,
                    drive2$StdPP, drive3$StdPP,
                    drive2$MeanPP_SegMax, drive3$MeanPP_SegMax, 
                    drive2$MeanPP_Seg0, drive3$MeanPP_Seg0,
                    drive2$StdPP_SegMax, drive3$StdPP_SegMax, 
                    drive2$StdPP_Seg0, drive3$StdPP_Seg0
                  )
names(combinedDf) <- c(names(drive4), 
                       "PP_Dev_1_Turning",
                       "PP_Dev_2", "PP_Dev_3", 
                       "Std_PP_2", "Std_PP_3",
                       "PP_Dev_2_Straight", "PP_Dev_3_Straight", 
                       "PP_Dev_2_Turning", "PP_Dev_3_Turning", 
                       "Std_PP_2_Straight", "Std_PP_3_Straight", 
                       "Std_PP_2_Turning", "Std_PP_3_Turning"
                       )

combinedDf$Subject <- paste0("#", str_pad(combinedDf$Subject, 2, pad="0"))
combinedDf_NoStressor <- combinedDf[combinedDf$Activity == "NO",]
combinedDf_Cognitive <- combinedDf[combinedDf$Activity == "C",]
combinedDf_Motoric <- combinedDf[combinedDf$Activity == "M",]

combinedDf_NoStressor$Subject <- as.factor(combinedDf_NoStressor$Subject)
combinedDf_Cognitive$Subject <- as.factor(combinedDf_Cognitive$Subject)
combinedDf_Motoric$Subject <- as.factor(combinedDf_Motoric$Subject)
COLOR_NORMAL <- list(color='rgb(120,120,120)')
COLOR_COGNITIVE <- list(color='rgb(158,202,225)')
COLOR_MOTORIC <- list(color='rgb(58,200,225)')
COLOR_FAILURE_PRIOR <- list(color='rgb(158,202,225)')
COLOR_FAILURE <- list(color='red')

yAxis <- list(
  title = 'Perinasal Perspiration (Log)',
  range=c(-0.3, 0.5)
)

# Apply Otsu algorithm to select threshold
ppDev <- combinedDf$PP_Dev
ppDevArray <- matrix(ppDev ,nrow = 1,ncol = length(ppDev))
  
THRESHOLD_MILD = otsu(ppDevArray, range=c(min(ppDev), max(ppDev))) # Expected Threshold > 0.042
print(paste0('Threshold: ', THRESHOLD_MILD))
[1] "Threshold: 0.062365390625"
MARKER_LINE_MILD = list(color="blue")
MARKER_LINE_EXTREME = list(color="red")
fig_NoStressor <- plot_ly(combinedDf_NoStressor, x = ~Subject, y = ~PP_Dev_2_Straight, type = 'bar', name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
  add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>% 
  add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>% 
  add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>% 
  add_trace(y = ~PP_Prior, name = 'Failure - Prior PP', marker=COLOR_FAILURE_PRIOR) %>% 
  add_trace(y = ~PP_Dev, name = 'Failure - PP Deviation', marker=COLOR_FAILURE) %>% 
  add_segments(x="#01", xend="#41", y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Threshold: Mild Change of PP",
                           line=list(color="blue", dash = 'dot')) %>%
  # add_segments(x="#01", xend="#41", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
  #                          line=list(color="darkred", dash = 'dot')) %>%
  layout(yaxis = yAxis, barmode = 'group', title="No Stressor")

htmltools::tagList(fig_NoStressor)
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
fig_Cognitive <- plot_ly(combinedDf_Cognitive, x = ~Subject, y = ~PP_Dev_2_Straight, type = 'bar', name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
  add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>% 
  add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>% 
  add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>% 
  add_trace(y = ~PP_Prior, name = 'Failure - Prior PP', marker=COLOR_FAILURE_PRIOR) %>% 
  add_trace(y = ~PP_Dev, name = 'Failure - PP Deviation', marker=COLOR_FAILURE) %>% 
  add_segments(x="#02", xend="#22", y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Threshold: Mild Change of PP",
                           line=list(color="blue", dash = 'dot')) %>%
  # add_segments(x="#02", xend="#22", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
  #                          line=list(color="darkred", dash = 'dot')) %>%
  layout(yaxis = yAxis, barmode = 'group', title="Stressor = Cognitive")

htmltools::tagList(fig_Cognitive)
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
fig_Motoric <- plot_ly(combinedDf_Motoric, x = ~Subject, y = ~PP_Dev_2_Straight, type = 'bar', name = 'Arousal in Drive C - Straight segment', marker=COLOR_COGNITIVE, width=870) %>%
  add_trace(y = ~PP_Dev_3_Straight, name = 'Arousal in Drive M - Straight segment', marker=COLOR_MOTORIC) %>% 
  add_trace(y = ~PP_Dev_2_Turning, name = 'Arousal in Drive C - Turning segment', marker=COLOR_COGNITIVE) %>% 
  add_trace(y = ~PP_Dev_3_Turning, name = 'Arousal in Drive M - Turning segment', marker=COLOR_MOTORIC) %>%
  add_trace(y = ~PP_Prior, name = 'Arousal in Drive F - Under prior stressor', marker=COLOR_FAILURE_PRIOR) %>% 
  add_trace(y = ~PP_Dev, name = 'Arousal in Drive F - Unintended acceleration', marker=COLOR_FAILURE) %>% 
  add_segments(x="#05", xend="#31", y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Threshold",
                           line=list(color="blue", dash = 'dot')) %>%
  # add_segments(x="#05", xend="#31", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
  #                          line=list(color="darkred", dash = 'dot')) %>%
  layout(yaxis = yAxis, barmode = 'group', title="Stressor = Motoric")

htmltools::tagList(fig_Motoric)
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
library(nlme)
combinedDf$Subject = as.factor(combinedDf$Subject)
combinedDf$Activity = as.factor(combinedDf$Activity)
combinedDf$PP_Dev_Group = ifelse(combinedDf$PP_Dev > THRESHOLD_MILD, 1, 0)

Extract data for important features

importantFeaturesDf <- combinedDf %>% select(Subject, Std_PP_3, PP_Dev_2_Turning, Activity, PP_Dev, PP_Dev_Group)

Linear model with all variables

combinedDfNoOutlier <- combinedDf[combinedDf$Subject != "#05",]
linearModel1 <- lm(PP_Dev ~ 
              + abs(PP_Dev_2_Straight)
              + abs(PP_Dev_3_Straight)
              + abs(PP_Dev_2_Turning) 
              + abs(PP_Dev_3_Turning)
              + Std_PP_2_Straight
              + Std_PP_3_Straight
              + Std_PP_2_Turning
              + Std_PP_3_Turning
              + abs(PP_Prior)
              + factor(Activity), 
            data=combinedDfNoOutlier)

# anova(model)
summary(linearModel1)

Call:
lm(formula = PP_Dev ~ +abs(PP_Dev_2_Straight) + abs(PP_Dev_3_Straight) + 
    abs(PP_Dev_2_Turning) + abs(PP_Dev_3_Turning) + Std_PP_2_Straight + 
    Std_PP_3_Straight + Std_PP_2_Turning + Std_PP_3_Turning + 
    abs(PP_Prior) + factor(Activity), data = combinedDfNoOutlier)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.061608 -0.023646 -0.001386  0.021675  0.056991 

Coefficients:
                       Estimate Std. Error t value Pr(>|t|)  
(Intercept)            -0.04855    0.09805  -0.495   0.6338  
abs(PP_Dev_2_Straight) -0.79389    0.38371  -2.069   0.0723 .
abs(PP_Dev_3_Straight) -0.88216    0.37883  -2.329   0.0483 *
abs(PP_Dev_2_Turning)   1.33096    0.42150   3.158   0.0134 *
abs(PP_Dev_3_Turning)   0.65528    0.41177   1.591   0.1502  
Std_PP_2_Straight      -0.02230    0.92083  -0.024   0.9813  
Std_PP_3_Straight       0.94069    0.54777   1.717   0.1243  
Std_PP_2_Turning       -0.04010    0.96553  -0.042   0.9679  
Std_PP_3_Turning       -0.68361    1.29563  -0.528   0.6121  
abs(PP_Prior)           0.60073    0.30309   1.982   0.0828 .
factor(Activity)M       0.07962    0.03836   2.076   0.0716 .
factor(Activity)NO     -0.10478    0.06432  -1.629   0.1420  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.0545 on 8 degrees of freedom
Multiple R-squared:  0.8453,    Adjusted R-squared:  0.6325 
F-statistic: 3.973 on 11 and 8 DF,  p-value: 0.03023
plot(linearModel1)

linearModel1 <- lm(PP_Dev ~ 
              + PP_Dev_2
              + PP_Dev_3
              + Std_PP_2
              + Std_PP_3, 
            data=combinedDfNoOutlier)

# anova(model)
summary(linearModel1)

Call:
lm(formula = PP_Dev ~ +PP_Dev_2 + PP_Dev_3 + Std_PP_2 + Std_PP_3, 
    data = combinedDfNoOutlier)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.12047 -0.04606 -0.01017  0.04443  0.10684 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)  
(Intercept) -0.13336    0.07723  -1.727   0.1048  
PP_Dev_2     0.16542    0.14765   1.120   0.2802  
PP_Dev_3    -0.33968    0.22814  -1.489   0.1572  
Std_PP_2     0.08517    0.45813   0.186   0.8550  
Std_PP_3     2.50981    1.04105   2.411   0.0292 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.07381 on 15 degrees of freedom
Multiple R-squared:  0.4679,    Adjusted R-squared:  0.3261 
F-statistic: 3.298 on 4 and 15 DF,  p-value: 0.0397
plot(linearModel1)

Linear Model from Drive C

linearModelC <- lm(PP_Dev ~
              PP_Dev_2_Straight
              + PP_Dev_2_Turning
              + Std_PP_2_Straight
              + Std_PP_2_Turning,
            data=combinedDf)

# anova(model)
summary(linearModelC)

Call:
lm(formula = PP_Dev ~ PP_Dev_2_Straight + PP_Dev_2_Turning + 
    Std_PP_2_Straight + Std_PP_2_Turning, data = combinedDf)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.13555 -0.05433  0.00251  0.05596  0.12635 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)
(Intercept)        0.02351    0.05388   0.436    0.668
PP_Dev_2_Straight -0.02887    0.26153  -0.110    0.913
PP_Dev_2_Turning   0.19976    0.30675   0.651    0.524
Std_PP_2_Straight  1.13112    0.84826   1.333    0.201
Std_PP_2_Turning  -0.62211    0.92511  -0.672    0.511

Residual standard error: 0.08441 on 16 degrees of freedom
Multiple R-squared:  0.258, Adjusted R-squared:  0.07249 
F-statistic: 1.391 on 4 and 16 DF,  p-value: 0.2816
plot(linearModelC)

linearModelC_Segments <- lm(PP_Dev ~ 
              PP_Dev_2
              + Std_PP_2,
            data=combinedDf)

# anova(model)
summary(linearModelC_Segments)

Call:
lm(formula = PP_Dev ~ PP_Dev_2 + Std_PP_2, data = combinedDf)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.14869 -0.05352 -0.01075  0.06704  0.13707 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept)  0.02784    0.04663   0.597    0.558
PP_Dev_2     0.15451    0.11497   1.344    0.196
Std_PP_2     0.47780    0.40255   1.187    0.251

Residual standard error: 0.08518 on 18 degrees of freedom
Multiple R-squared:  0.1498,    Adjusted R-squared:  0.05531 
F-statistic: 1.585 on 2 and 18 DF,  p-value: 0.2322
plot(linearModelC_Segments)

Linear Model from Drive M

linearModelM <- lm(PP_Dev ~ 
              PP_Dev_3
              + Std_PP_3
              + factor(Activity),
            data=combinedDfNoOutlier)

# anova(model)
summary(linearModelM)

Call:
lm(formula = PP_Dev ~ PP_Dev_3 + Std_PP_3 + factor(Activity), 
    data = combinedDfNoOutlier)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.08243 -0.05948 -0.00697  0.05039  0.10987 

Coefficients:
                    Estimate Std. Error t value Pr(>|t|)  
(Intercept)        -0.110401   0.082369  -1.340   0.2001  
PP_Dev_3           -0.070627   0.178377  -0.396   0.6977  
Std_PP_3            2.020000   0.947378   2.132   0.0499 *
factor(Activity)M   0.068144   0.044012   1.548   0.1424  
factor(Activity)NO -0.001664   0.038375  -0.043   0.9660  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.07078 on 15 degrees of freedom
Multiple R-squared:  0.5107,    Adjusted R-squared:  0.3802 
F-statistic: 3.914 on 4 and 15 DF,  p-value: 0.02269
plot(linearModelM)

linearModelM <- lm(PP_Dev ~ 
              PP_Dev_3_Straight
              + PP_Dev_3_Turning
              + Std_PP_3_Straight
              + Std_PP_3_Turning,
            data=combinedDfNoOutlier)

# anova(model)
summary(linearModelM)

Call:
lm(formula = PP_Dev ~ PP_Dev_3_Straight + PP_Dev_3_Turning + 
    Std_PP_3_Straight + Std_PP_3_Turning, data = combinedDfNoOutlier)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.09868 -0.05695 -0.01233  0.06261  0.10188 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)  
(Intercept)       -0.15580    0.07868  -1.980   0.0663 .
PP_Dev_3_Straight -0.74334    0.36299  -2.048   0.0585 .
PP_Dev_3_Turning   0.64682    0.42651   1.517   0.1502  
Std_PP_3_Straight  0.88491    0.69611   1.271   0.2230  
Std_PP_3_Turning   1.81284    0.93698   1.935   0.0721 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.07454 on 15 degrees of freedom
Multiple R-squared:  0.4574,    Adjusted R-squared:  0.3127 
F-statistic: 3.162 on 4 and 15 DF,  p-value: 0.04517
plot(linearModelM)

# Export the anova table
library(xtable)
lmCoeffs <- summary(linearModel1)$coefficients
lmAnova <- anova(linearModel1)

print(xtable(lmCoeffs, digits=c(0,5,5,5,5)))
% latex table generated in R 3.6.1 by xtable 1.8-4 package
% Fri Jul 10 00:42:45 2020
\begin{table}[ht]
\centering
\begin{tabular}{rrrrr}
  \hline
 & Estimate & Std. Error & t value & Pr($>$$|$t$|$) \\ 
  \hline
(Intercept) & -0.13336 & 0.07723 & -1.72671 & 0.10475 \\ 
  PP\_Dev\_2 & 0.16542 & 0.14765 & 1.12038 & 0.28017 \\ 
  PP\_Dev\_3 & -0.33968 & 0.22814 & -1.48892 & 0.15723 \\ 
  Std\_PP\_2 & 0.08517 & 0.45813 & 0.18591 & 0.85500 \\ 
  Std\_PP\_3 & 2.50981 & 1.04105 & 2.41085 & 0.02920 \\ 
   \hline
\end{tabular}
\end{table}
print(xtable(lmAnova), digits=c(0,5,5,5,5))
% latex table generated in R 3.6.1 by xtable 1.8-4 package
% Fri Jul 10 00:42:45 2020
\begin{table}[ht]
\centering
\begin{tabular}{lrrrrr}
  \hline
 & Df & Sum Sq & Mean Sq & F value & Pr($>$F) \\ 
  \hline
PP\_Dev\_2 & 1 & 0.01 & 0.01 & 2.37 & 0.1445 \\ 
  PP\_Dev\_3 & 1 & 0.01 & 0.01 & 1.31 & 0.2706 \\ 
  Std\_PP\_2 & 1 & 0.02 & 0.02 & 3.70 & 0.0735 \\ 
  Std\_PP\_3 & 1 & 0.03 & 0.03 & 5.81 & 0.0292 \\ 
  Residuals & 15 & 0.08 & 0.01 &  &  \\ 
   \hline
\end{tabular}
\end{table}
combinedDf$PP_Dev <- NULL

combinedDf$Subject <- NULL
combinedDf$Activity_NO <- ifelse(combinedDf$Activity == "NO", 1, 0)
combinedDf$Activity_C <- ifelse(combinedDf$Activity == "C", 1, 0)
combinedDf$Activity_M <- ifelse(combinedDf$Activity == "M", 1, 0)
combinedDf$Activity <- NULL
combinedDf$PP_Dev_1_Turning <- NULL

combinedDf$Std_PP_2_Straight <- NULL
combinedDf$Std_PP_2_Turning <- NULL
combinedDf$Std_PP_3_Straight <- NULL
combinedDf$Std_PP_3_Turning <- NULL

# According to Linear model
combinedDf$PP_Dev_2_Straight <- abs(combinedDf$PP_Dev_2_Straight)
combinedDf$PP_Dev_3_Straight <- abs(combinedDf$PP_Dev_3_Straight)
combinedDf$PP_Dev_2_Turning <- abs(combinedDf$PP_Dev_2_Turning)
combinedDf$PP_Dev_3_Turning <- abs(combinedDf$PP_Dev_3_Turning)
combinedDf$PP_Prior <- abs(combinedDf$PP_Prior) # NULL

combinedDf$Class <- ifelse(combinedDf$PP_Dev_Group == 1, T, F)
combinedDf$PP_Dev_Group <- NULL

print(names(combinedDf))
 [1] "PP_Prior"          "PP_Dev_2"          "PP_Dev_3"          "Std_PP_2"          "Std_PP_3"          "PP_Dev_2_Straight"
 [7] "PP_Dev_3_Straight" "PP_Dev_2_Turning"  "PP_Dev_3_Turning"  "Activity_NO"       "Activity_C"        "Activity_M"       
[13] "Class"            
# library(mefa)
# combinedDf <- rep(combinedDf, 10) 
set.seed(39)
n_folds <- 3
params <- param <- list(objective       = "binary:logistic", 
               booster          = "gbtree",
               eval_metric      = "auc",
               eta              = 0.1,
               max_depth        = 10,
               alpha            = 1,
               lambda           = 0,
               gamma            = 0.45,
               min_child_weight = 0.3,
               subsample        = 1,
               colsample_bytree = 1)
           
# XGBoost Model         
xgb_m <- xgb.cv(   params               = param,
                  data = as.matrix(combinedDf %>% select(-Class)) ,
                  label =  combinedDf$Class,
                  nrounds             = 100,
                  verbose             = F,
                  prediction          = T,
                  maximize            = T, # Change this value to F will help to run with more itineration
                  nfold               = n_folds,
                  metrics             = c("auc", "error"),
                  early_stopping_rounds = 50,
                  stratified            = T,
                  scale_pos_weight      = 7/14)

# xgb_m$evaluation_log[xgb_m$best_iteration,"test_auc_mean"]
xgb_m$evaluation_log[xgb_m$best_iteration,]
NA
# Prediction
combinedDf$clsPred <- round(xgb_m$pred)

computePerformanceResults <- function(sdat){
  sdat = sdat[complete.cases(sdat),]
  acc = sum(sdat[,1] == sdat[,2])/nrow(sdat)
  conf_mat = table(sdat)
  specif = conf_mat[1,1]/sum(conf_mat[,1])
  sensiv = conf_mat[2,2]/sum(conf_mat[,2])
  preci =  conf_mat[2,2]/sum(conf_mat[2,])
  npv =    conf_mat[1,1]/sum(conf_mat[1,])
  return(c(acc,specif,sensiv,preci,npv))
}

# Get average performance
performance <- computePerformanceResults(combinedDf %>% select(Class, clsPred))
acc <- performance[1]
prec <- performance[4]
recall <- performance[3]
spec <- performance[2]
npv <- performance[5]
f1 <- (2 * recall * prec) / (recall + prec)
auc <- as.numeric(xgb_m$evaluation_log[xgb_m$best_iteration, "test_auc_mean"])

print(paste("Accuracy=", round(acc, 2)))
[1] "Accuracy= 0.9"
print(paste("Precision=", round(prec, 2)))
[1] "Precision= 0.92"
print(paste("Recall=", round(recall, 2)))
[1] "Recall= 0.92"
print(paste("Specificity=", round(spec, 2)))
[1] "Specificity= 0.88"
print(paste("NPV=", round(npv, 2)))
[1] "NPV= 0.88"
print(paste("F1=", round(f1, 2)))
[1] "F1= 0.92"
print(paste("AUC=", round(auc, 2)))
[1] "AUC= 0.91"
# Importance
bst <- xgboost(   params               = param,
                  data = as.matrix(combinedDf %>% select(-Class)) ,
                  label =  combinedDf$Class,
                  nrounds             = 100,
                  verbose             = F,
                  prediction          = T,
                  maximize            = T, # Change this value to F will help to run with more itineration
                  nfold               = n_folds,
                  metrics             = c("auc", "error"),
                  early_stopping_rounds = 50,
                  stratified            = T,
                  scale_pos_weight      = 1)
importanceDf <- xgb.importance(colnames(combinedDf), model = bst)
print(importanceDf)
library(pROC)

dfROC <- pROC::roc(response = ifelse(combinedDf$Class==T, 1, 0),
               predictor = round(xgb_m$pred),
               levels=c(0, 1), direction = "<")

# it = which.max(xgb_m$evaluation_log$test_auc_mean)
# best.iter = xgb_m$evaluation_log$iter[it]
# best.iter 

plot(pROC::roc(response = ifelse(combinedDf$Class==T, 1, 0),
               predictor = round(xgb_m$pred),
               levels=c(0, 1), direction = "<"), 
     legacy.axes = TRUE,
     main="ROC Curve", 
     lwd=1.5) 

Important features

# Eleminate #5 who has an exceptional data to find a better threshold
stdPP3 <- sort(importantFeaturesDf$Std_PP_3, decreasing = T)[2:length(importantFeaturesDf$Std_PP_3)]
stdPP3Array <- matrix(stdPP3 ,nrow = 1,ncol = length(stdPP3))
  
maxStdPP3 <- sort(importantFeaturesDf$Std_PP_3, decreasing = T)[2]
PP_DEV_3_THRESHOLD <- otsu(stdPP3Array, range=c(min(stdPP3), maxStdPP3)) # Expected Threshold = 0.088
print(paste0('Threshold: ', PP_DEV_3_THRESHOLD))
[1] "Threshold: 0.0881111526518663"
importantFeaturesDf$PP_Dev_3_Group <- ifelse(importantFeaturesDf$Std_PP_3 > PP_DEV_3_THRESHOLD, 1, 0)
write.csv(importantFeaturesDf, "../outputs/importantFeatures.csv")

Venn diagram

library(VennDiagram)
library(RColorBrewer)
 
M_Low <- rownames(importantFeaturesDf[importantFeaturesDf$PP_Dev_3_Group==0,])
M_High <- rownames(importantFeaturesDf[importantFeaturesDf$PP_Dev_3_Group==1,])

F_Low <- rownames(importantFeaturesDf[importantFeaturesDf$PP_Dev_Group==0,])
F_High <- rownames(importantFeaturesDf[importantFeaturesDf$PP_Dev_Group==1,])

jpeg("../plots/venn/venn_All.png", res=150, width=900)
venn.plot <- venn.diagram(
  list(M_Low, F_Low, M_High, F_High), NULL, 
  fill=c("blue", "blue", "red", "red"), 
  alpha=c(0.5,0.5,0.5,0.5), 
  resolution = 150,
  cex = 1, 
  cat.fontface=1, 
  category.names=c("Drive=M\n SD=Low\n", "Drive=F\n Arousal=Low\n", "Drive=M\n SD=High\n", "Drive=F\n Arousal=High\n")
)
grid.draw(venn.plot)
dev.off()
null device 
          1 
# 
# jpeg("../plots/venn/venn_High.png", res=150, width=700)
# venn.plot <- venn.diagram(
#   list(M_High, F_High), NULL, 
#   fill=c("pink", "red"), 
#   alpha=c(0.5,0.5), 
#   resolution = 150,
#   cex = 1, 
#   cat.fontface=1, 
#   category.names=c("Drive=M", "Drive=F")
# )
# grid.draw(venn.plot)
# dev.off()

Plot feature importance

yAxis <- list(
  title = 'Importance',
  range=c(0.0, 1.0)
)
xAxis <- list(
  title = ''
)
importanceDf$FeatureName <- lapply(importanceDf$Feature, function(x) {
  ifelse(x=="Std_PP_3", "SD of Arousal\n in Drive M", 
         ifelse(x=="PP_Dev_2_Turning", "Arousal in Drive C\nat turning segments", 
            ifelse(x=="Activity_C", "Prior stressor\n is Cognitive", x)))
})

fig_Importance <- plot_ly(importanceDf, x = ~FeatureName, y = ~Gain, type = 'bar', name = 'Gain', width=600) %>%
  add_trace(y = ~Cover, name = 'Cover') %>% 
  add_trace(y = ~Frequency, name = 'Frequency') %>% 
  layout(yaxis = yAxis, xaxis=xAxis, barmode = 'group', title="Feature Importance") %>% 
  config(.Last.value, mathjax = 'cdn')

htmltools::tagList(fig_Importance)

Feature

classColors <- c("blue", "red")
figStdVsDev <- plot_ly(data = importantFeaturesDf, x = ~Std_PP_3, y = ~PP_Dev, 
                       color=~factor(PP_Dev_Group), colors=classColors,
                       marker=list(text="X")) %>%
  layout(xaxis=list(title="SD of Arousal in Motoric Drive \n Hyphenated line indicates discriminative boundary"), yaxis=list(title="Arousal at catastrophic event"), showscale=F) %>%
  layout(shapes=list(
    list(x0=0.088, x1=0.088, y0=-0.1, y1=0.25, line=list(dash="dot", width=1, color="green"))
  ))
htmltools::tagList(figStdVsDev)
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
'layout' objects don't have these attributes: 'showscale'
Valid attributes include:
'font', 'title', 'autosize', 'width', 'height', 'margin', 'paper_bgcolor', 'plot_bgcolor', 'separators', 'hidesources', 'showlegend', 'colorway', 'datarevision', 'uirevision', 'editrevision', 'selectionrevision', 'template', 'modebar', 'meta', 'transition', '_deprecated', 'clickmode', 'dragmode', 'hovermode', 'hoverdistance', 'spikedistance', 'hoverlabel', 'selectdirection', 'grid', 'calendar', 'xaxis', 'yaxis', 'ternary', 'scene', 'geo', 'mapbox', 'polar', 'radialaxis', 'angularaxis', 'direction', 'orientation', 'editType', 'legend', 'annotations', 'shapes', 'images', 'updatemenus', 'sliders', 'colorscale', 'coloraxis', 'metasrc', 'barmode', 'bargap', 'mapType'
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
'layout' objects don't have these attributes: 'showscale'
Valid attributes include:
'font', 'title', 'autosize', 'width', 'height', 'margin', 'paper_bgcolor', 'plot_bgcolor', 'separators', 'hidesources', 'showlegend', 'colorway', 'datarevision', 'uirevision', 'editrevision', 'selectionrevision', 'template', 'modebar', 'meta', 'transition', '_deprecated', 'clickmode', 'dragmode', 'hovermode', 'hoverdistance', 'spikedistance', 'hoverlabel', 'selectdirection', 'grid', 'calendar', 'xaxis', 'yaxis', 'ternary', 'scene', 'geo', 'mapbox', 'polar', 'radialaxis', 'angularaxis', 'direction', 'orientation', 'editType', 'legend', 'annotations', 'shapes', 'images', 'updatemenus', 'sliders', 'colorscale', 'coloraxis', 'metasrc', 'barmode', 'bargap', 'mapType'
classColors <- c("blue", "red")
figStdVsDev <- plot_ly(data = importantFeaturesDf, x = ~abs(PP_Dev_2_Turning), y = ~PP_Dev, 
                       color=~factor(PP_Dev_Group), colors=classColors,
                       marker=list(text="X")) %>%
  layout(xaxis=list(title="SD of Arousal in Motoric Drive"), yaxis=list(title="Arousal at catastrophic event")) %>%
  layout(shapes=list(
    list(x0=0.088, x1=0.088, y0=-0.1, y1=0.25, line=list(dash="dot", width=1))
  ))
htmltools::tagList(figStdVsDev)
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
classColors <- c("blue", "red")
figStdVsDev <- plot_ly(data = importantFeaturesDf, y = ~abs(PP_Dev_2_Turning), x = ~Std_PP_3, 
                       color=~factor(PP_Dev_Group), colors=classColors,
                       marker=list(text="X")) %>%
  layout(xaxis=list(title="SD of Arousal in Motoric Drive"), yaxis=list(title="Arousal at catastrophic event"), showscale=F) %>%
  layout(shapes=list(
    list(x0=0.088, x1=0.088, y0=-0.1, y1=0.25, line=list(dash="dot", width=1))
  ))
htmltools::tagList(figStdVsDev)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CnNvdXJjZSgnLi4vc2V0dGluZ3Mvc2V0dGluZ3MuUicpCnNvdXJjZSgnY29tbW9uRnVuY3Rpb25zLlInKQpgYGAKCmBgYHtyfQpkcml2ZTEgPC0gcmVhZC5jc3YoJy4uL2RhdGEvcHJvY2Vzc2VkL2FuYWx5c2lzL1RUMV9Ecml2ZV8xX1BQLmNzdicpCmRyaXZlMiA8LSByZWFkLmNzdignLi4vZGF0YS9wcm9jZXNzZWQvQW5hbHlzaXMvVFQxX0RyaXZlXzJfUFAuY3N2JykKZHJpdmUzIDwtIHJlYWQuY3N2KCcuLi9kYXRhL3Byb2Nlc3NlZC9BbmFseXNpcy9UVDFfRHJpdmVfM19QUC5jc3YnKQpkcml2ZTQgPC0gcmVhZC5jc3YoJy4uL2RhdGEvcHJvY2Vzc2VkL0FuYWx5c2lzL1RUMV9Ecml2ZV80X1BQLmNzdicsIHN0cmluZ3NBc0ZhY3RvcnMgPSBUKQpgYGAKCmBgYHtyfQpzZXQuc2VlZCg0MykKY29tYmluZWREZiA8LSBjYmluZChkcml2ZTQsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMSRNZWFuUFBfU2VnMCwgCiAgICAgICAgICAgICAgICAgICAgZHJpdmUyJE1lYW5QUCwgZHJpdmUzJE1lYW5QUCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkU3RkUFAsIGRyaXZlMyRTdGRQUCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkTWVhblBQX1NlZ01heCwgZHJpdmUzJE1lYW5QUF9TZWdNYXgsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRNZWFuUFBfU2VnMCwgZHJpdmUzJE1lYW5QUF9TZWcwLAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRTdGRQUF9TZWdNYXgsIGRyaXZlMyRTdGRQUF9TZWdNYXgsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRTdGRQUF9TZWcwLCBkcml2ZTMkU3RkUFBfU2VnMAogICAgICAgICAgICAgICAgICApCm5hbWVzKGNvbWJpbmVkRGYpIDwtIGMobmFtZXMoZHJpdmU0KSwgCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8xX1R1cm5pbmciLAogICAgICAgICAgICAgICAgICAgICAgICJQUF9EZXZfMiIsICJQUF9EZXZfMyIsIAogICAgICAgICAgICAgICAgICAgICAgICJTdGRfUFBfMiIsICJTdGRfUFBfMyIsCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8yX1N0cmFpZ2h0IiwgIlBQX0Rldl8zX1N0cmFpZ2h0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8yX1R1cm5pbmciLCAiUFBfRGV2XzNfVHVybmluZyIsIAogICAgICAgICAgICAgICAgICAgICAgICJTdGRfUFBfMl9TdHJhaWdodCIsICJTdGRfUFBfM19TdHJhaWdodCIsIAogICAgICAgICAgICAgICAgICAgICAgICJTdGRfUFBfMl9UdXJuaW5nIiwgIlN0ZF9QUF8zX1R1cm5pbmciCiAgICAgICAgICAgICAgICAgICAgICAgKQoKY29tYmluZWREZiRTdWJqZWN0IDwtIHBhc3RlMCgiIyIsIHN0cl9wYWQoY29tYmluZWREZiRTdWJqZWN0LCAyLCBwYWQ9IjAiKSkKYGBgCgpgYGB7cn0KY29tYmluZWREZl9Ob1N0cmVzc29yIDwtIGNvbWJpbmVkRGZbY29tYmluZWREZiRBY3Rpdml0eSA9PSAiTk8iLF0KY29tYmluZWREZl9Db2duaXRpdmUgPC0gY29tYmluZWREZltjb21iaW5lZERmJEFjdGl2aXR5ID09ICJDIixdCmNvbWJpbmVkRGZfTW90b3JpYyA8LSBjb21iaW5lZERmW2NvbWJpbmVkRGYkQWN0aXZpdHkgPT0gIk0iLF0KCmNvbWJpbmVkRGZfTm9TdHJlc3NvciRTdWJqZWN0IDwtIGFzLmZhY3Rvcihjb21iaW5lZERmX05vU3RyZXNzb3IkU3ViamVjdCkKY29tYmluZWREZl9Db2duaXRpdmUkU3ViamVjdCA8LSBhcy5mYWN0b3IoY29tYmluZWREZl9Db2duaXRpdmUkU3ViamVjdCkKY29tYmluZWREZl9Nb3RvcmljJFN1YmplY3QgPC0gYXMuZmFjdG9yKGNvbWJpbmVkRGZfTW90b3JpYyRTdWJqZWN0KQpgYGAKCmBgYHtyfQpDT0xPUl9OT1JNQUwgPC0gbGlzdChjb2xvcj0ncmdiKDEyMCwxMjAsMTIwKScpCkNPTE9SX0NPR05JVElWRSA8LSBsaXN0KGNvbG9yPSdyZ2IoMTU4LDIwMiwyMjUpJykKQ09MT1JfTU9UT1JJQyA8LSBsaXN0KGNvbG9yPSdyZ2IoNTgsMjAwLDIyNSknKQpDT0xPUl9GQUlMVVJFX1BSSU9SIDwtIGxpc3QoY29sb3I9J3JnYigxNTgsMjAyLDIyNSknKQpDT0xPUl9GQUlMVVJFIDwtIGxpc3QoY29sb3I9J3JlZCcpCgp5QXhpcyA8LSBsaXN0KAogIHRpdGxlID0gJ1BlcmluYXNhbCBQZXJzcGlyYXRpb24gKExvZyknLAogIHJhbmdlPWMoLTAuMywgMC41KQopCgojIEFwcGx5IE90c3UgYWxnb3JpdGhtIHRvIHNlbGVjdCB0aHJlc2hvbGQKcHBEZXYgPC0gY29tYmluZWREZiRQUF9EZXYKcHBEZXZBcnJheSA8LSBtYXRyaXgocHBEZXYgLG5yb3cgPSAxLG5jb2wgPSBsZW5ndGgocHBEZXYpKQogIApUSFJFU0hPTERfTUlMRCA9IG90c3UocHBEZXZBcnJheSwgcmFuZ2U9YyhtaW4ocHBEZXYpLCBtYXgocHBEZXYpKSkgIyBFeHBlY3RlZCBUaHJlc2hvbGQgPiAwLjA0MgpwcmludChwYXN0ZTAoJ1RocmVzaG9sZDogJywgVEhSRVNIT0xEX01JTEQpKQoKTUFSS0VSX0xJTkVfTUlMRCA9IGxpc3QoY29sb3I9ImJsdWUiKQpNQVJLRVJfTElORV9FWFRSRU1FID0gbGlzdChjb2xvcj0icmVkIikKYGBgCgpgYGB7ciwgd2FybmluZz1GfQpmaWdfTm9TdHJlc3NvciA8LSBwbG90X2x5KGNvbWJpbmVkRGZfTm9TdHJlc3NvciwgeCA9IH5TdWJqZWN0LCB5ID0gflBQX0Rldl8yX1N0cmFpZ2h0LCB0eXBlID0gJ2JhcicsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoU3RyYWlnaHQpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfU3RyYWlnaHQsIG5hbWUgPSAnTW90b3JpYyAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzJfVHVybmluZywgbmFtZSA9ICdDb2duaXRpdmUgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JSAKICBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfM19UdXJuaW5nLCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfUHJpb3IsIG5hbWUgPSAnRmFpbHVyZSAtIFByaW9yIFBQJywgbWFya2VyPUNPTE9SX0ZBSUxVUkVfUFJJT1IpICU+JSAKICBhZGRfdHJhY2UoeSA9IH5QUF9EZXYsIG5hbWUgPSAnRmFpbHVyZSAtIFBQIERldmlhdGlvbicsIG1hcmtlcj1DT0xPUl9GQUlMVVJFKSAlPiUgCiAgYWRkX3NlZ21lbnRzKHg9IiMwMSIsIHhlbmQ9IiM0MSIsIHkgPSBUSFJFU0hPTERfTUlMRCwgeWVuZCA9IFRIUkVTSE9MRF9NSUxELCBuYW1lPSJUaHJlc2hvbGQ6IE1pbGQgQ2hhbmdlIG9mIFBQIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgIyBhZGRfc2VnbWVudHMoeD0iIzAxIiwgeGVuZD0iIzQxIiwgeSA9IFRIUkVTSE9MRF9FWFRSRU1FLCB5ZW5kID0gVEhSRVNIT0xEX0VYVFJFTUUsIG5hbWU9IlRocmVzaG9sZDogRXh0cmVtZSBDaGFuZ2Ugb2YgUFAiLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iZGFya3JlZCIsIGRhc2ggPSAnZG90JykpICU+JQogIGxheW91dCh5YXhpcyA9IHlBeGlzLCBiYXJtb2RlID0gJ2dyb3VwJywgdGl0bGU9Ik5vIFN0cmVzc29yIikKCmh0bWx0b29sczo6dGFnTGlzdChmaWdfTm9TdHJlc3NvcikKYGBgCgpgYGB7ciwgd2FybmluZz1GfQpmaWdfQ29nbml0aXZlIDwtIHBsb3RfbHkoY29tYmluZWREZl9Db2duaXRpdmUsIHggPSB+U3ViamVjdCwgeSA9IH5QUF9EZXZfMl9TdHJhaWdodCwgdHlwZSA9ICdiYXInLCBuYW1lID0gJ0NvZ25pdGl2ZSAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JQogIGFkZF90cmFjZSh5ID0gflBQX0Rldl8zX1N0cmFpZ2h0LCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChTdHJhaWdodCknLCBtYXJrZXI9Q09MT1JfTU9UT1JJQykgJT4lIAogIGFkZF90cmFjZSh5ID0gflBQX0Rldl8yX1R1cm5pbmcsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoVHVybmluZyknLCBtYXJrZXI9Q09MT1JfQ09HTklUSVZFKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfVHVybmluZywgbmFtZSA9ICdNb3RvcmljIC0gTWVhbiBQUCAoVHVybmluZyknLCBtYXJrZXI9Q09MT1JfTU9UT1JJQykgJT4lIAogIGFkZF90cmFjZSh5ID0gflBQX1ByaW9yLCBuYW1lID0gJ0ZhaWx1cmUgLSBQcmlvciBQUCcsIG1hcmtlcj1DT0xPUl9GQUlMVVJFX1BSSU9SKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2LCBuYW1lID0gJ0ZhaWx1cmUgLSBQUCBEZXZpYXRpb24nLCBtYXJrZXI9Q09MT1JfRkFJTFVSRSkgJT4lIAogIGFkZF9zZWdtZW50cyh4PSIjMDIiLCB4ZW5kPSIjMjIiLCB5ID0gVEhSRVNIT0xEX01JTEQsIHllbmQgPSBUSFJFU0hPTERfTUlMRCwgbmFtZT0iVGhyZXNob2xkOiBNaWxkIENoYW5nZSBvZiBQUCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2ggPSAnZG90JykpICU+JQogICMgYWRkX3NlZ21lbnRzKHg9IiMwMiIsIHhlbmQ9IiMyMiIsIHkgPSBUSFJFU0hPTERfRVhUUkVNRSwgeWVuZCA9IFRIUkVTSE9MRF9FWFRSRU1FLCBuYW1lPSJUaHJlc2hvbGQ6IEV4dHJlbWUgQ2hhbmdlIG9mIFBQIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImRhcmtyZWQiLCBkYXNoID0gJ2RvdCcpKSAlPiUKICBsYXlvdXQoeWF4aXMgPSB5QXhpcywgYmFybW9kZSA9ICdncm91cCcsIHRpdGxlPSJTdHJlc3NvciA9IENvZ25pdGl2ZSIpCgpodG1sdG9vbHM6OnRhZ0xpc3QoZmlnX0NvZ25pdGl2ZSkKYGBgCgoKCmBgYHtyLCB3YXJuaW5nPUZ9CmZpZ19Nb3RvcmljIDwtIHBsb3RfbHkoY29tYmluZWREZl9Nb3RvcmljLCB4ID0gflN1YmplY3QsIHkgPSB+UFBfRGV2XzJfU3RyYWlnaHQsIHR5cGUgPSAnYmFyJywgbmFtZSA9ICdBcm91c2FsIGluIERyaXZlIEMgLSBTdHJhaWdodCBzZWdtZW50JywgbWFya2VyPUNPTE9SX0NPR05JVElWRSwgd2lkdGg9ODcwKSAlPiUKICBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfM19TdHJhaWdodCwgbmFtZSA9ICdBcm91c2FsIGluIERyaXZlIE0gLSBTdHJhaWdodCBzZWdtZW50JywgbWFya2VyPUNPTE9SX01PVE9SSUMpICU+JSAKICBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfMl9UdXJuaW5nLCBuYW1lID0gJ0Fyb3VzYWwgaW4gRHJpdmUgQyAtIFR1cm5pbmcgc2VnbWVudCcsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JSAKICBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfM19UdXJuaW5nLCBuYW1lID0gJ0Fyb3VzYWwgaW4gRHJpdmUgTSAtIFR1cm5pbmcgc2VnbWVudCcsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUKICBhZGRfdHJhY2UoeSA9IH5QUF9QcmlvciwgbmFtZSA9ICdBcm91c2FsIGluIERyaXZlIEYgLSBVbmRlciBwcmlvciBzdHJlc3NvcicsIG1hcmtlcj1DT0xPUl9GQUlMVVJFX1BSSU9SKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2LCBuYW1lID0gJ0Fyb3VzYWwgaW4gRHJpdmUgRiAtIFVuaW50ZW5kZWQgYWNjZWxlcmF0aW9uJywgbWFya2VyPUNPTE9SX0ZBSUxVUkUpICU+JSAKICBhZGRfc2VnbWVudHMoeD0iIzA1IiwgeGVuZD0iIzMxIiwgeSA9IFRIUkVTSE9MRF9NSUxELCB5ZW5kID0gVEhSRVNIT0xEX01JTEQsIG5hbWU9IlRocmVzaG9sZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2ggPSAnZG90JykpICU+JQogICMgYWRkX3NlZ21lbnRzKHg9IiMwNSIsIHhlbmQ9IiMzMSIsIHkgPSBUSFJFU0hPTERfRVhUUkVNRSwgeWVuZCA9IFRIUkVTSE9MRF9FWFRSRU1FLCBuYW1lPSJUaHJlc2hvbGQ6IEV4dHJlbWUgQ2hhbmdlIG9mIFBQIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImRhcmtyZWQiLCBkYXNoID0gJ2RvdCcpKSAlPiUKICBsYXlvdXQoeWF4aXMgPSB5QXhpcywgYmFybW9kZSA9ICdncm91cCcsIHRpdGxlPSJTdHJlc3NvciA9IE1vdG9yaWMiKQoKaHRtbHRvb2xzOjp0YWdMaXN0KGZpZ19Nb3RvcmljKQpgYGAKCgpgYGB7cn0KbGlicmFyeShubG1lKQpjb21iaW5lZERmJFN1YmplY3QgPSBhcy5mYWN0b3IoY29tYmluZWREZiRTdWJqZWN0KQpjb21iaW5lZERmJEFjdGl2aXR5ID0gYXMuZmFjdG9yKGNvbWJpbmVkRGYkQWN0aXZpdHkpCmNvbWJpbmVkRGYkUFBfRGV2X0dyb3VwID0gaWZlbHNlKGNvbWJpbmVkRGYkUFBfRGV2ID4gVEhSRVNIT0xEX01JTEQsIDEsIDApCmBgYAoKIyMjIEV4dHJhY3QgZGF0YSBmb3IgaW1wb3J0YW50IGZlYXR1cmVzCmBgYHtyfQppbXBvcnRhbnRGZWF0dXJlc0RmIDwtIGNvbWJpbmVkRGYgJT4lIHNlbGVjdChTdWJqZWN0LCBTdGRfUFBfMywgUFBfRGV2XzJfVHVybmluZywgQWN0aXZpdHksIFBQX0RldiwgUFBfRGV2X0dyb3VwKQpgYGAKCiMgTGluZWFyIG1vZGVsIHdpdGggYWxsIHZhcmlhYmxlcwpgYGB7cn0KY29tYmluZWREZk5vT3V0bGllciA8LSBjb21iaW5lZERmW2NvbWJpbmVkRGYkU3ViamVjdCAhPSAiIzA1IixdCmxpbmVhck1vZGVsMSA8LSBsbShQUF9EZXYgfiAKICAgICAgICAgICAgICArIGFicyhQUF9EZXZfMl9TdHJhaWdodCkKICAgICAgICAgICAgICArIGFicyhQUF9EZXZfM19TdHJhaWdodCkKICAgICAgICAgICAgICArIGFicyhQUF9EZXZfMl9UdXJuaW5nKSAKICAgICAgICAgICAgICArIGFicyhQUF9EZXZfM19UdXJuaW5nKQogICAgICAgICAgICAgICsgU3RkX1BQXzJfU3RyYWlnaHQKICAgICAgICAgICAgICArIFN0ZF9QUF8zX1N0cmFpZ2h0CiAgICAgICAgICAgICAgKyBTdGRfUFBfMl9UdXJuaW5nCiAgICAgICAgICAgICAgKyBTdGRfUFBfM19UdXJuaW5nCiAgICAgICAgICAgICAgKyBhYnMoUFBfUHJpb3IpCiAgICAgICAgICAgICAgKyBmYWN0b3IoQWN0aXZpdHkpLCAKICAgICAgICAgICAgZGF0YT1jb21iaW5lZERmTm9PdXRsaWVyKQoKIyBhbm92YShtb2RlbCkKc3VtbWFyeShsaW5lYXJNb2RlbDEpCnBsb3QobGluZWFyTW9kZWwxKQpgYGAKCmBgYHtyfQpsaW5lYXJNb2RlbDEgPC0gbG0oUFBfRGV2IH4gCiAgICAgICAgICAgICAgKyBQUF9EZXZfMgogICAgICAgICAgICAgICsgUFBfRGV2XzMKICAgICAgICAgICAgICArIFN0ZF9QUF8yCiAgICAgICAgICAgICAgKyBTdGRfUFBfMywgCiAgICAgICAgICAgIGRhdGE9Y29tYmluZWREZk5vT3V0bGllcikKCiMgYW5vdmEobW9kZWwpCnN1bW1hcnkobGluZWFyTW9kZWwxKQpwbG90KGxpbmVhck1vZGVsMSkKYGBgCgoKIyBMaW5lYXIgTW9kZWwgZnJvbSBEcml2ZSBDCmBgYHtyfQpsaW5lYXJNb2RlbEMgPC0gbG0oUFBfRGV2IH4KICAgICAgICAgICAgICBQUF9EZXZfMl9TdHJhaWdodAogICAgICAgICAgICAgICsgUFBfRGV2XzJfVHVybmluZwogICAgICAgICAgICAgICsgU3RkX1BQXzJfU3RyYWlnaHQKICAgICAgICAgICAgICArIFN0ZF9QUF8yX1R1cm5pbmcsCiAgICAgICAgICAgIGRhdGE9Y29tYmluZWREZikKCiMgYW5vdmEobW9kZWwpCnN1bW1hcnkobGluZWFyTW9kZWxDKQpwbG90KGxpbmVhck1vZGVsQykKYGBgCgpgYGB7cn0KbGluZWFyTW9kZWxDX1NlZ21lbnRzIDwtIGxtKFBQX0RldiB+IAogICAgICAgICAgICAgIFBQX0Rldl8yCiAgICAgICAgICAgICAgKyBTdGRfUFBfMiwKICAgICAgICAgICAgZGF0YT1jb21iaW5lZERmKQoKIyBhbm92YShtb2RlbCkKc3VtbWFyeShsaW5lYXJNb2RlbENfU2VnbWVudHMpCnBsb3QobGluZWFyTW9kZWxDX1NlZ21lbnRzKQpgYGAKCiMgTGluZWFyIE1vZGVsIGZyb20gRHJpdmUgTQpgYGB7cn0KbGluZWFyTW9kZWxNIDwtIGxtKFBQX0RldiB+IAogICAgICAgICAgICAgIFBQX0Rldl8zCiAgICAgICAgICAgICAgKyBTdGRfUFBfMwogICAgICAgICAgICAgICsgZmFjdG9yKEFjdGl2aXR5KSwKICAgICAgICAgICAgZGF0YT1jb21iaW5lZERmTm9PdXRsaWVyKQoKIyBhbm92YShtb2RlbCkKc3VtbWFyeShsaW5lYXJNb2RlbE0pCnBsb3QobGluZWFyTW9kZWxNKQpgYGAKYGBge3J9CmxpbmVhck1vZGVsTSA8LSBsbShQUF9EZXYgfiAKICAgICAgICAgICAgICBQUF9EZXZfM19TdHJhaWdodAogICAgICAgICAgICAgICsgUFBfRGV2XzNfVHVybmluZwogICAgICAgICAgICAgICsgU3RkX1BQXzNfU3RyYWlnaHQKICAgICAgICAgICAgICArIFN0ZF9QUF8zX1R1cm5pbmcsCiAgICAgICAgICAgIGRhdGE9Y29tYmluZWREZk5vT3V0bGllcikKCiMgYW5vdmEobW9kZWwpCnN1bW1hcnkobGluZWFyTW9kZWxNKQpwbG90KGxpbmVhck1vZGVsTSkKYGBgCgpgYGB7cn0KIyBFeHBvcnQgdGhlIGFub3ZhIHRhYmxlCmxpYnJhcnkoeHRhYmxlKQpsbUNvZWZmcyA8LSBzdW1tYXJ5KGxpbmVhck1vZGVsMSkkY29lZmZpY2llbnRzCmxtQW5vdmEgPC0gYW5vdmEobGluZWFyTW9kZWwxKQoKcHJpbnQoeHRhYmxlKGxtQ29lZmZzLCBkaWdpdHM9YygwLDUsNSw1LDUpKSkKcHJpbnQoeHRhYmxlKGxtQW5vdmEpLCBkaWdpdHM9YygwLDUsNSw1LDUpKQoKYGBgCgoKYGBge3J9CmNvbWJpbmVkRGYkUFBfRGV2IDwtIE5VTEwKCmNvbWJpbmVkRGYkU3ViamVjdCA8LSBOVUxMCmNvbWJpbmVkRGYkQWN0aXZpdHlfTk8gPC0gaWZlbHNlKGNvbWJpbmVkRGYkQWN0aXZpdHkgPT0gIk5PIiwgMSwgMCkKY29tYmluZWREZiRBY3Rpdml0eV9DIDwtIGlmZWxzZShjb21iaW5lZERmJEFjdGl2aXR5ID09ICJDIiwgMSwgMCkKY29tYmluZWREZiRBY3Rpdml0eV9NIDwtIGlmZWxzZShjb21iaW5lZERmJEFjdGl2aXR5ID09ICJNIiwgMSwgMCkKY29tYmluZWREZiRBY3Rpdml0eSA8LSBOVUxMCmNvbWJpbmVkRGYkUFBfRGV2XzFfVHVybmluZyA8LSBOVUxMCgpjb21iaW5lZERmJFN0ZF9QUF8yX1N0cmFpZ2h0IDwtIE5VTEwKY29tYmluZWREZiRTdGRfUFBfMl9UdXJuaW5nIDwtIE5VTEwKY29tYmluZWREZiRTdGRfUFBfM19TdHJhaWdodCA8LSBOVUxMCmNvbWJpbmVkRGYkU3RkX1BQXzNfVHVybmluZyA8LSBOVUxMCgojIEFjY29yZGluZyB0byBMaW5lYXIgbW9kZWwKY29tYmluZWREZiRQUF9EZXZfMl9TdHJhaWdodCA8LSBhYnMoY29tYmluZWREZiRQUF9EZXZfMl9TdHJhaWdodCkKY29tYmluZWREZiRQUF9EZXZfM19TdHJhaWdodCA8LSBhYnMoY29tYmluZWREZiRQUF9EZXZfM19TdHJhaWdodCkKY29tYmluZWREZiRQUF9EZXZfMl9UdXJuaW5nIDwtIGFicyhjb21iaW5lZERmJFBQX0Rldl8yX1R1cm5pbmcpCmNvbWJpbmVkRGYkUFBfRGV2XzNfVHVybmluZyA8LSBhYnMoY29tYmluZWREZiRQUF9EZXZfM19UdXJuaW5nKQpjb21iaW5lZERmJFBQX1ByaW9yIDwtIGFicyhjb21iaW5lZERmJFBQX1ByaW9yKSAjIE5VTEwKCmNvbWJpbmVkRGYkQ2xhc3MgPC0gaWZlbHNlKGNvbWJpbmVkRGYkUFBfRGV2X0dyb3VwID09IDEsIFQsIEYpCmNvbWJpbmVkRGYkUFBfRGV2X0dyb3VwIDwtIE5VTEwKCnByaW50KG5hbWVzKGNvbWJpbmVkRGYpKQpgYGAKCmBgYHtyfQojIGxpYnJhcnkobWVmYSkKIyBjb21iaW5lZERmIDwtIHJlcChjb21iaW5lZERmLCAxMCkgCmBgYAoKYGBge3J9CnNldC5zZWVkKDM5KQpuX2ZvbGRzIDwtIDMKcGFyYW1zIDwtIHBhcmFtIDwtIGxpc3Qob2JqZWN0aXZlICAgICAgID0gImJpbmFyeTpsb2dpc3RpYyIsIAogICAgICAgICAgICAgICBib29zdGVyICAgICAgICAgID0gImdidHJlZSIsCiAgICAgICAgICAgICAgIGV2YWxfbWV0cmljICAgICAgPSAiYXVjIiwKICAgICAgICAgICAgICAgZXRhICAgICAgICAgICAgICA9IDAuMSwKICAgICAgICAgICAgICAgbWF4X2RlcHRoICAgICAgICA9IDEwLAogICAgICAgICAgICAgICBhbHBoYSAgICAgICAgICAgID0gMSwKICAgICAgICAgICAgICAgbGFtYmRhICAgICAgICAgICA9IDAsCiAgICAgICAgICAgICAgIGdhbW1hICAgICAgICAgICAgPSAwLjQ1LAogICAgICAgICAgICAgICBtaW5fY2hpbGRfd2VpZ2h0ID0gMC4zLAogICAgICAgICAgICAgICBzdWJzYW1wbGUgICAgICAgID0gMSwKICAgICAgICAgICAgICAgY29sc2FtcGxlX2J5dHJlZSA9IDEpCiAgICAgICAgICAgCiMgWEdCb29zdCBNb2RlbCAgICAgICAgIAp4Z2JfbSA8LSB4Z2IuY3YoICAgcGFyYW1zICAgICAgICAgICAgICAgPSBwYXJhbSwKICAgICAgICAgICAgICAgICAgZGF0YSA9IGFzLm1hdHJpeChjb21iaW5lZERmICU+JSBzZWxlY3QoLUNsYXNzKSkgLAogICAgICAgICAgICAgICAgICBsYWJlbCA9ICBjb21iaW5lZERmJENsYXNzLAogICAgICAgICAgICAgICAgICBucm91bmRzICAgICAgICAgICAgID0gMTAwLAogICAgICAgICAgICAgICAgICB2ZXJib3NlICAgICAgICAgICAgID0gRiwKICAgICAgICAgICAgICAgICAgcHJlZGljdGlvbiAgICAgICAgICA9IFQsCiAgICAgICAgICAgICAgICAgIG1heGltaXplICAgICAgICAgICAgPSBULCAjIENoYW5nZSB0aGlzIHZhbHVlIHRvIEYgd2lsbCBoZWxwIHRvIHJ1biB3aXRoIG1vcmUgaXRpbmVyYXRpb24KICAgICAgICAgICAgICAgICAgbmZvbGQgICAgICAgICAgICAgICA9IG5fZm9sZHMsCiAgICAgICAgICAgICAgICAgIG1ldHJpY3MgICAgICAgICAgICAgPSBjKCJhdWMiLCAiZXJyb3IiKSwKICAgICAgICAgICAgICAgICAgZWFybHlfc3RvcHBpbmdfcm91bmRzID0gNTAsCiAgICAgICAgICAgICAgICAgIHN0cmF0aWZpZWQgICAgICAgICAgICA9IFQsCiAgICAgICAgICAgICAgICAgIHNjYWxlX3Bvc193ZWlnaHQgICAgICA9IDcvMTQpCgojIHhnYl9tJGV2YWx1YXRpb25fbG9nW3hnYl9tJGJlc3RfaXRlcmF0aW9uLCJ0ZXN0X2F1Y19tZWFuIl0KeGdiX20kZXZhbHVhdGlvbl9sb2dbeGdiX20kYmVzdF9pdGVyYXRpb24sXQoKYGBgCmBgYHtyfQojIFByZWRpY3Rpb24KY29tYmluZWREZiRjbHNQcmVkIDwtIHJvdW5kKHhnYl9tJHByZWQpCgpjb21wdXRlUGVyZm9ybWFuY2VSZXN1bHRzIDwtIGZ1bmN0aW9uKHNkYXQpewogIHNkYXQgPSBzZGF0W2NvbXBsZXRlLmNhc2VzKHNkYXQpLF0KICBhY2MgPSBzdW0oc2RhdFssMV0gPT0gc2RhdFssMl0pL25yb3coc2RhdCkKICBjb25mX21hdCA9IHRhYmxlKHNkYXQpCiAgc3BlY2lmID0gY29uZl9tYXRbMSwxXS9zdW0oY29uZl9tYXRbLDFdKQogIHNlbnNpdiA9IGNvbmZfbWF0WzIsMl0vc3VtKGNvbmZfbWF0WywyXSkKICBwcmVjaSA9ICBjb25mX21hdFsyLDJdL3N1bShjb25mX21hdFsyLF0pCiAgbnB2ID0gICAgY29uZl9tYXRbMSwxXS9zdW0oY29uZl9tYXRbMSxdKQogIHJldHVybihjKGFjYyxzcGVjaWYsc2Vuc2l2LHByZWNpLG5wdikpCn0KCiMgR2V0IGF2ZXJhZ2UgcGVyZm9ybWFuY2UKcGVyZm9ybWFuY2UgPC0gY29tcHV0ZVBlcmZvcm1hbmNlUmVzdWx0cyhjb21iaW5lZERmICU+JSBzZWxlY3QoQ2xhc3MsIGNsc1ByZWQpKQphY2MgPC0gcGVyZm9ybWFuY2VbMV0KcHJlYyA8LSBwZXJmb3JtYW5jZVs0XQpyZWNhbGwgPC0gcGVyZm9ybWFuY2VbM10Kc3BlYyA8LSBwZXJmb3JtYW5jZVsyXQpucHYgPC0gcGVyZm9ybWFuY2VbNV0KZjEgPC0gKDIgKiByZWNhbGwgKiBwcmVjKSAvIChyZWNhbGwgKyBwcmVjKQphdWMgPC0gYXMubnVtZXJpYyh4Z2JfbSRldmFsdWF0aW9uX2xvZ1t4Z2JfbSRiZXN0X2l0ZXJhdGlvbiwgInRlc3RfYXVjX21lYW4iXSkKCnByaW50KHBhc3RlKCJBY2N1cmFjeT0iLCByb3VuZChhY2MsIDIpKSkKcHJpbnQocGFzdGUoIlByZWNpc2lvbj0iLCByb3VuZChwcmVjLCAyKSkpCnByaW50KHBhc3RlKCJSZWNhbGw9Iiwgcm91bmQocmVjYWxsLCAyKSkpCnByaW50KHBhc3RlKCJTcGVjaWZpY2l0eT0iLCByb3VuZChzcGVjLCAyKSkpCnByaW50KHBhc3RlKCJOUFY9Iiwgcm91bmQobnB2LCAyKSkpCnByaW50KHBhc3RlKCJGMT0iLCByb3VuZChmMSwgMikpKQpwcmludChwYXN0ZSgiQVVDPSIsIHJvdW5kKGF1YywgMikpKQpgYGAKCmBgYHtyfQojIEltcG9ydGFuY2UKYnN0IDwtIHhnYm9vc3QoICAgcGFyYW1zICAgICAgICAgICAgICAgPSBwYXJhbSwKICAgICAgICAgICAgICAgICAgZGF0YSA9IGFzLm1hdHJpeChjb21iaW5lZERmICU+JSBzZWxlY3QoLUNsYXNzKSkgLAogICAgICAgICAgICAgICAgICBsYWJlbCA9ICBjb21iaW5lZERmJENsYXNzLAogICAgICAgICAgICAgICAgICBucm91bmRzICAgICAgICAgICAgID0gMTAwLAogICAgICAgICAgICAgICAgICB2ZXJib3NlICAgICAgICAgICAgID0gRiwKICAgICAgICAgICAgICAgICAgcHJlZGljdGlvbiAgICAgICAgICA9IFQsCiAgICAgICAgICAgICAgICAgIG1heGltaXplICAgICAgICAgICAgPSBULCAjIENoYW5nZSB0aGlzIHZhbHVlIHRvIEYgd2lsbCBoZWxwIHRvIHJ1biB3aXRoIG1vcmUgaXRpbmVyYXRpb24KICAgICAgICAgICAgICAgICAgbmZvbGQgICAgICAgICAgICAgICA9IG5fZm9sZHMsCiAgICAgICAgICAgICAgICAgIG1ldHJpY3MgICAgICAgICAgICAgPSBjKCJhdWMiLCAiZXJyb3IiKSwKICAgICAgICAgICAgICAgICAgZWFybHlfc3RvcHBpbmdfcm91bmRzID0gNTAsCiAgICAgICAgICAgICAgICAgIHN0cmF0aWZpZWQgICAgICAgICAgICA9IFQsCiAgICAgICAgICAgICAgICAgIHNjYWxlX3Bvc193ZWlnaHQgICAgICA9IDEpCmltcG9ydGFuY2VEZiA8LSB4Z2IuaW1wb3J0YW5jZShjb2xuYW1lcyhjb21iaW5lZERmKSwgbW9kZWwgPSBic3QpCnByaW50KGltcG9ydGFuY2VEZikKYGBgCgpgYGB7cn0KbGlicmFyeShwUk9DKQoKZGZST0MgPC0gcFJPQzo6cm9jKHJlc3BvbnNlID0gaWZlbHNlKGNvbWJpbmVkRGYkQ2xhc3M9PVQsIDEsIDApLAogICAgICAgICAgICAgICBwcmVkaWN0b3IgPSByb3VuZCh4Z2JfbSRwcmVkKSwKICAgICAgICAgICAgICAgbGV2ZWxzPWMoMCwgMSksIGRpcmVjdGlvbiA9ICI8IikKCiMgaXQgPSB3aGljaC5tYXgoeGdiX20kZXZhbHVhdGlvbl9sb2ckdGVzdF9hdWNfbWVhbikKIyBiZXN0Lml0ZXIgPSB4Z2JfbSRldmFsdWF0aW9uX2xvZyRpdGVyW2l0XQojIGJlc3QuaXRlciAKCnBsb3QocFJPQzo6cm9jKHJlc3BvbnNlID0gaWZlbHNlKGNvbWJpbmVkRGYkQ2xhc3M9PVQsIDEsIDApLAogICAgICAgICAgICAgICBwcmVkaWN0b3IgPSByb3VuZCh4Z2JfbSRwcmVkKSwKICAgICAgICAgICAgICAgbGV2ZWxzPWMoMCwgMSksIGRpcmVjdGlvbiA9ICI8IiksIAogICAgIGxlZ2FjeS5heGVzID0gVFJVRSwKICAgICBtYWluPSJST0MgQ3VydmUiLCAKICAgICBsd2Q9MS41KSAKYGBgCgojIEltcG9ydGFudCBmZWF0dXJlcwpgYGB7cn0KIyBFbGVtaW5hdGUgIzUgd2hvIGhhcyBhbiBleGNlcHRpb25hbCBkYXRhIHRvIGZpbmQgYSBiZXR0ZXIgdGhyZXNob2xkCnN0ZFBQMyA8LSBzb3J0KGltcG9ydGFudEZlYXR1cmVzRGYkU3RkX1BQXzMsIGRlY3JlYXNpbmcgPSBUKVsyOmxlbmd0aChpbXBvcnRhbnRGZWF0dXJlc0RmJFN0ZF9QUF8zKV0Kc3RkUFAzQXJyYXkgPC0gbWF0cml4KHN0ZFBQMyAsbnJvdyA9IDEsbmNvbCA9IGxlbmd0aChzdGRQUDMpKQogIAptYXhTdGRQUDMgPC0gc29ydChpbXBvcnRhbnRGZWF0dXJlc0RmJFN0ZF9QUF8zLCBkZWNyZWFzaW5nID0gVClbMl0KUFBfREVWXzNfVEhSRVNIT0xEIDwtIG90c3Uoc3RkUFAzQXJyYXksIHJhbmdlPWMobWluKHN0ZFBQMyksIG1heFN0ZFBQMykpICMgRXhwZWN0ZWQgVGhyZXNob2xkID0gMC4wODgKcHJpbnQocGFzdGUwKCdUaHJlc2hvbGQ6ICcsIFBQX0RFVl8zX1RIUkVTSE9MRCkpCgppbXBvcnRhbnRGZWF0dXJlc0RmJFBQX0Rldl8zX0dyb3VwIDwtIGlmZWxzZShpbXBvcnRhbnRGZWF0dXJlc0RmJFN0ZF9QUF8zID4gUFBfREVWXzNfVEhSRVNIT0xELCAxLCAwKQp3cml0ZS5jc3YoaW1wb3J0YW50RmVhdHVyZXNEZiwgIi4uL291dHB1dHMvaW1wb3J0YW50RmVhdHVyZXMuY3N2IikKYGBgCgojIFZlbm4gZGlhZ3JhbQpgYGB7cn0KbGlicmFyeShWZW5uRGlhZ3JhbSkKbGlicmFyeShSQ29sb3JCcmV3ZXIpCiAKTV9Mb3cgPC0gcm93bmFtZXMoaW1wb3J0YW50RmVhdHVyZXNEZltpbXBvcnRhbnRGZWF0dXJlc0RmJFBQX0Rldl8zX0dyb3VwPT0wLF0pCk1fSGlnaCA8LSByb3duYW1lcyhpbXBvcnRhbnRGZWF0dXJlc0RmW2ltcG9ydGFudEZlYXR1cmVzRGYkUFBfRGV2XzNfR3JvdXA9PTEsXSkKCkZfTG93IDwtIHJvd25hbWVzKGltcG9ydGFudEZlYXR1cmVzRGZbaW1wb3J0YW50RmVhdHVyZXNEZiRQUF9EZXZfR3JvdXA9PTAsXSkKRl9IaWdoIDwtIHJvd25hbWVzKGltcG9ydGFudEZlYXR1cmVzRGZbaW1wb3J0YW50RmVhdHVyZXNEZiRQUF9EZXZfR3JvdXA9PTEsXSkKCmpwZWcoIi4uL3Bsb3RzL3Zlbm4vdmVubl9BbGwucG5nIiwgcmVzPTE1MCwgd2lkdGg9OTAwKQp2ZW5uLnBsb3QgPC0gdmVubi5kaWFncmFtKAogIGxpc3QoTV9Mb3csIEZfTG93LCBNX0hpZ2gsIEZfSGlnaCksIE5VTEwsIAogIGZpbGw9YygiYmx1ZSIsICJibHVlIiwgInJlZCIsICJyZWQiKSwgCiAgYWxwaGE9YygwLjUsMC41LDAuNSwwLjUpLCAKICByZXNvbHV0aW9uID0gMTUwLAogIGNleCA9IDEsIAogIGNhdC5mb250ZmFjZT0xLCAKICBjYXRlZ29yeS5uYW1lcz1jKCJEcml2ZT1NXG4gU0Q9TG93XG4iLCAiRHJpdmU9RlxuIEFyb3VzYWw9TG93XG4iLCAiRHJpdmU9TVxuIFNEPUhpZ2hcbiIsICJEcml2ZT1GXG4gQXJvdXNhbD1IaWdoXG4iKQopCmdyaWQuZHJhdyh2ZW5uLnBsb3QpCmRldi5vZmYoKQojIAojIGpwZWcoIi4uL3Bsb3RzL3Zlbm4vdmVubl9IaWdoLnBuZyIsIHJlcz0xNTAsIHdpZHRoPTcwMCkKIyB2ZW5uLnBsb3QgPC0gdmVubi5kaWFncmFtKAojICAgbGlzdChNX0hpZ2gsIEZfSGlnaCksIE5VTEwsIAojICAgZmlsbD1jKCJwaW5rIiwgInJlZCIpLCAKIyAgIGFscGhhPWMoMC41LDAuNSksIAojICAgcmVzb2x1dGlvbiA9IDE1MCwKIyAgIGNleCA9IDEsIAojICAgY2F0LmZvbnRmYWNlPTEsIAojICAgY2F0ZWdvcnkubmFtZXM9YygiRHJpdmU9TSIsICJEcml2ZT1GIikKIyApCiMgZ3JpZC5kcmF3KHZlbm4ucGxvdCkKIyBkZXYub2ZmKCkKYGBgCgojIyMgUGxvdCBmZWF0dXJlIGltcG9ydGFuY2UKYGBge3J9CnlBeGlzIDwtIGxpc3QoCiAgdGl0bGUgPSAnSW1wb3J0YW5jZScsCiAgcmFuZ2U9YygwLjAsIDEuMCkKKQp4QXhpcyA8LSBsaXN0KAogIHRpdGxlID0gJycKKQppbXBvcnRhbmNlRGYkRmVhdHVyZU5hbWUgPC0gbGFwcGx5KGltcG9ydGFuY2VEZiRGZWF0dXJlLCBmdW5jdGlvbih4KSB7CiAgaWZlbHNlKHg9PSJTdGRfUFBfMyIsICJTRCBvZiBBcm91c2FsXG4gaW4gRHJpdmUgTSIsIAogICAgICAgICBpZmVsc2UoeD09IlBQX0Rldl8yX1R1cm5pbmciLCAiQXJvdXNhbCBpbiBEcml2ZSBDXG5hdCB0dXJuaW5nIHNlZ21lbnRzIiwgCiAgICAgICAgICAgIGlmZWxzZSh4PT0iQWN0aXZpdHlfQyIsICJQcmlvciBzdHJlc3NvclxuIGlzIENvZ25pdGl2ZSIsIHgpKSkKfSkKCmZpZ19JbXBvcnRhbmNlIDwtIHBsb3RfbHkoaW1wb3J0YW5jZURmLCB4ID0gfkZlYXR1cmVOYW1lLCB5ID0gfkdhaW4sIHR5cGUgPSAnYmFyJywgbmFtZSA9ICdHYWluJywgd2lkdGg9NjAwKSAlPiUKICBhZGRfdHJhY2UoeSA9IH5Db3ZlciwgbmFtZSA9ICdDb3ZlcicpICU+JSAKICBhZGRfdHJhY2UoeSA9IH5GcmVxdWVuY3ksIG5hbWUgPSAnRnJlcXVlbmN5JykgJT4lIAogIGxheW91dCh5YXhpcyA9IHlBeGlzLCB4YXhpcz14QXhpcywgYmFybW9kZSA9ICdncm91cCcsIHRpdGxlPSJGZWF0dXJlIEltcG9ydGFuY2UiKSAlPiUgCiAgY29uZmlnKC5MYXN0LnZhbHVlLCBtYXRoamF4ID0gJ2NkbicpCgpodG1sdG9vbHM6OnRhZ0xpc3QoZmlnX0ltcG9ydGFuY2UpCmBgYAoKIyMjIEZlYXR1cmUKYGBge3J9CmNsYXNzQ29sb3JzIDwtIGMoImJsdWUiLCAicmVkIikKZmlnU3RkVnNEZXYgPC0gcGxvdF9seShkYXRhID0gaW1wb3J0YW50RmVhdHVyZXNEZiwgeCA9IH5TdGRfUFBfMywgeSA9IH5QUF9EZXYsIAogICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPX5mYWN0b3IoUFBfRGV2X0dyb3VwKSwgY29sb3JzPWNsYXNzQ29sb3JzLAogICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcj1saXN0KHRleHQ9IlgiKSkgJT4lCiAgbGF5b3V0KHhheGlzPWxpc3QodGl0bGU9IlNEIG9mIEFyb3VzYWwgaW4gTW90b3JpYyBEcml2ZSBcbiBIeXBoZW5hdGVkIGxpbmUgaW5kaWNhdGVzIGRpc2NyaW1pbmF0aXZlIGJvdW5kYXJ5IiksIHlheGlzPWxpc3QodGl0bGU9IkFyb3VzYWwgYXQgY2F0YXN0cm9waGljIGV2ZW50IiksIHNob3dzY2FsZT1GKSAlPiUKICBsYXlvdXQoc2hhcGVzPWxpc3QoCiAgICBsaXN0KHgwPTAuMDg4LCB4MT0wLjA4OCwgeTA9LTAuMSwgeTE9MC4yNSwgbGluZT1saXN0KGRhc2g9ImRvdCIsIHdpZHRoPTEsIGNvbG9yPSJncmVlbiIpKQogICkpCmh0bWx0b29sczo6dGFnTGlzdChmaWdTdGRWc0RldikKYGBgCgpgYGB7cn0KY2xhc3NDb2xvcnMgPC0gYygiYmx1ZSIsICJyZWQiKQpmaWdTdGRWc0RldiA8LSBwbG90X2x5KGRhdGEgPSBpbXBvcnRhbnRGZWF0dXJlc0RmLCB4ID0gfmFicyhQUF9EZXZfMl9UdXJuaW5nKSwgeSA9IH5QUF9EZXYsIAogICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPX5mYWN0b3IoUFBfRGV2X0dyb3VwKSwgY29sb3JzPWNsYXNzQ29sb3JzLAogICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcj1saXN0KHRleHQ9IlgiKSkgJT4lCiAgbGF5b3V0KHhheGlzPWxpc3QodGl0bGU9IlNEIG9mIEFyb3VzYWwgaW4gTW90b3JpYyBEcml2ZSIpLCB5YXhpcz1saXN0KHRpdGxlPSJBcm91c2FsIGF0IGNhdGFzdHJvcGhpYyBldmVudCIpKSAlPiUKICBsYXlvdXQoc2hhcGVzPWxpc3QoCiAgICBsaXN0KHgwPTAuMDg4LCB4MT0wLjA4OCwgeTA9LTAuMSwgeTE9MC4yNSwgbGluZT1saXN0KGRhc2g9ImRvdCIsIHdpZHRoPTEpKQogICkpCmh0bWx0b29sczo6dGFnTGlzdChmaWdTdGRWc0RldikKYGBgCgpgYGB7cn0KY2xhc3NDb2xvcnMgPC0gYygiYmx1ZSIsICJyZWQiKQpmaWdTdGRWc0RldiA8LSBwbG90X2x5KGRhdGEgPSBpbXBvcnRhbnRGZWF0dXJlc0RmLCB5ID0gfmFicyhQUF9EZXZfMl9UdXJuaW5nKSwgeCA9IH5TdGRfUFBfMywgCiAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9fmZhY3RvcihQUF9EZXZfR3JvdXApLCBjb2xvcnM9Y2xhc3NDb2xvcnMsCiAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyPWxpc3QodGV4dD0iWCIpKSAlPiUKICBsYXlvdXQoeGF4aXM9bGlzdCh0aXRsZT0iU0Qgb2YgQXJvdXNhbCBpbiBNb3RvcmljIERyaXZlIiksIHlheGlzPWxpc3QodGl0bGU9IkFyb3VzYWwgYXQgY2F0YXN0cm9waGljIGV2ZW50IiksIHNob3dzY2FsZT1GKSAlPiUKICBsYXlvdXQoc2hhcGVzPWxpc3QoCiAgICBsaXN0KHgwPTAuMDg4LCB4MT0wLjA4OCwgeTA9LTAuMSwgeTE9MC4yNSwgbGluZT1saXN0KGRhc2g9ImRvdCIsIHdpZHRoPTEpKQogICkpCmh0bWx0b29sczo6dGFnTGlzdChmaWdTdGRWc0RldikKYGBgCgoK